1 package org.apache.lucene.index;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Random;
25
26 import org.apache.lucene.analysis.MockAnalyzer;
27 import org.apache.lucene.search.DocIdSetIterator;
28 import org.apache.lucene.store.Directory;
29 import org.apache.lucene.store.MockDirectoryWrapper;
30 import org.apache.lucene.store.RAMDirectory;
31 import org.apache.lucene.util.ArrayUtil;
32 import org.apache.lucene.util.Bits;
33 import org.apache.lucene.util.BytesRef;
34 import org.apache.lucene.util.LuceneTestCase;
35 import org.apache.lucene.util.TestUtil;
36
37 public class TestPerSegmentDeletes extends LuceneTestCase {
38 public void testDeletes1() throws Exception {
39
40 Directory dir = new MockDirectoryWrapper(new Random(random().nextLong()), new RAMDirectory());
41 IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random()));
42 iwc.setMergeScheduler(new SerialMergeScheduler());
43 iwc.setMaxBufferedDocs(5000);
44 iwc.setRAMBufferSizeMB(100);
45 RangeMergePolicy fsmp = new RangeMergePolicy(false);
46 iwc.setMergePolicy(fsmp);
47 IndexWriter writer = new IndexWriter(dir, iwc);
48 for (int x = 0; x < 5; x++) {
49 writer.addDocument(DocHelper.createDocument(x, "1", 2));
50
51 }
52
53 writer.commit();
54 assertEquals(1, writer.segmentInfos.size());
55 for (int x = 5; x < 10; x++) {
56 writer.addDocument(DocHelper.createDocument(x, "2", 2));
57
58 }
59
60 writer.commit();
61 assertEquals(2, writer.segmentInfos.size());
62
63 for (int x = 10; x < 15; x++) {
64 writer.addDocument(DocHelper.createDocument(x, "3", 2));
65
66 }
67
68 writer.deleteDocuments(new Term("id", "1"));
69
70 writer.deleteDocuments(new Term("id", "11"));
71
72
73
74 writer.flush(false, false);
75 assertTrue(writer.bufferedUpdatesStream.any());
76
77
78
79 IndexReader r1 = writer.getReader();
80 assertFalse(writer.bufferedUpdatesStream.any());
81 r1.close();
82
83
84
85
86 writer.deleteDocuments(new Term("id", "2"));
87 writer.flush(false, false);
88 fsmp = (RangeMergePolicy) writer.getConfig().getMergePolicy();
89 fsmp.doMerge = true;
90 fsmp.start = 0;
91 fsmp.length = 2;
92 writer.maybeMerge();
93
94 assertEquals(2, writer.segmentInfos.size());
95
96
97
98 IndexReader r2 = writer.getReader();
99 int[] id2docs = toDocsArray(new Term("id", "2"), null, r2);
100 assertTrue(id2docs == null);
101 r2.close();
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 writer.close();
163 dir.close();
164 }
165
166
167
168
169
170
171
172
173
174
175
176 void part2(IndexWriter writer, RangeMergePolicy fsmp) throws Exception {
177 for (int x = 20; x < 25; x++) {
178 writer.addDocument(DocHelper.createDocument(x, "5", 2));
179
180 }
181 writer.flush(false, false);
182 for (int x = 25; x < 30; x++) {
183 writer.addDocument(DocHelper.createDocument(x, "5", 2));
184
185 }
186 writer.flush(false, false);
187
188
189
190 Term delterm = new Term("id", "8");
191 writer.deleteDocuments(delterm);
192
193
194 fsmp.doMerge = true;
195 fsmp.start = 1;
196 fsmp.length = 2;
197 writer.maybeMerge();
198
199
200
201
202
203
204
205
206
207 }
208
209 boolean segThere(SegmentCommitInfo info, SegmentInfos infos) {
210 for (SegmentCommitInfo si : infos) {
211 if (si.info.name.equals(info.info.name)) return true;
212 }
213 return false;
214 }
215
216 public static void printDelDocs(Bits bits) {
217 if (bits == null) return;
218 for (int x = 0; x < bits.length(); x++) {
219 System.out.println(x + ":" + bits.get(x));
220 }
221 }
222
223 public int[] toDocsArray(Term term, Bits bits, IndexReader reader)
224 throws IOException {
225 Fields fields = MultiFields.getFields(reader);
226 Terms cterms = fields.terms(term.field);
227 TermsEnum ctermsEnum = cterms.iterator();
228 if (ctermsEnum.seekExact(new BytesRef(term.text()))) {
229 PostingsEnum postingsEnum = TestUtil.docs(random(), ctermsEnum, null, PostingsEnum.NONE);
230 return toArray(postingsEnum);
231 }
232 return null;
233 }
234
235 public static int[] toArray(PostingsEnum postingsEnum) throws IOException {
236 List<Integer> docs = new ArrayList<>();
237 while (postingsEnum.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) {
238 int docID = postingsEnum.docID();
239 docs.add(docID);
240 }
241 return ArrayUtil.toIntArray(docs);
242 }
243
244 public class RangeMergePolicy extends MergePolicy {
245 boolean doMerge = false;
246 int start;
247 int length;
248
249 private final boolean useCompoundFile;
250
251 private RangeMergePolicy(boolean useCompoundFile) {
252 this.useCompoundFile = useCompoundFile;
253 }
254
255 @Override
256 public MergeSpecification findMerges(MergeTrigger mergeTrigger, SegmentInfos segmentInfos, IndexWriter writer)
257 throws IOException {
258 MergeSpecification ms = new MergeSpecification();
259 if (doMerge) {
260 OneMerge om = new OneMerge(segmentInfos.asList().subList(start, start + length));
261 ms.add(om);
262 doMerge = false;
263 return ms;
264 }
265 return null;
266 }
267
268 @Override
269 public MergeSpecification findForcedMerges(SegmentInfos segmentInfos,
270 int maxSegmentCount, Map<SegmentCommitInfo,Boolean> segmentsToMerge, IndexWriter writer)
271 throws IOException {
272 return null;
273 }
274
275 @Override
276 public MergeSpecification findForcedDeletesMerges(
277 SegmentInfos segmentInfos, IndexWriter writer) throws IOException {
278 return null;
279 }
280
281 @Override
282 public boolean useCompoundFile(SegmentInfos segments, SegmentCommitInfo newSegment, IndexWriter writer) {
283 return useCompoundFile;
284 }
285 }
286 }